import os
import json
import asyncio
import openai
import pandas as pd

# 自定义函数来处理中文和其他不安全字符
def safe_filename(filename):
    # 保留中文字符，替换不安全的字符
    filename = re.sub(r'[^\w\s.-]', '', filename)  # 去掉不安全字符，但保留中文
    return filename

# Flask App 配置
app = Flask(__name__)

# 动态获取脚本所在目录，并确保上传文件夹存在
base_dir = os.path.dirname(os.path.abspath(__file__))
app.config['UPLOAD_FOLDER'] = os.path.join(base_dir, 'uploads')
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

# GPT 配置
openai.api_key = ""  # 你的 API key
temperature = 0

# 存储 system prompts 的 JSON 文件路径
PROMPT_JSON_FILE = 'prompt.json'

# 加载 JSON prompts
def load_prompts():
    if not os.path.exists(PROMPT_JSON_FILE):
       return []
    with open(PROMPT_JSON_FILE, 'r', encoding='utf-8') as f:
    f save_prompts(prompts):
    with open(PROMPT_JSON_FILE, 'w', encoding='utf-8') as f:
        json.dump(prompts, f, indent=4, ensure_ascii=False)

# GPT 请求同步函数
d    return json.load(f)

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # 如果是上传的 Excel 文件
        if 'file' in request.files:
            file = request.files['file']
            if file.filename == '':
                return redirect(request.url)

            # 使用自定义的 safe_filename 保留中文字符并确保安全
            original_filename = safe_filename(file.filename)
            if not original_filename.endswith('.xlsx'):
                original_filename += '.xlsx'  # 确保文件有 .xlsx 扩展名

            file_path = os.path.join(app.config['UPLOAD_FOLDER'], original_filename)
            file.save(file_path)

            # 选择的 prompt
            selected_prompt_title = request.form.get('prompt')
            prompts = load_prompts()
            selected_prompt = next((p['content'] for p in prompts if p['title'] == selected_prompt_title), "")

            # 异步处理 Excel
            try:
                asyncio.run(process_excel(file_path, selected_prompt))
            except RuntimeError as e:
                print(f"Asyncio RuntimeError: {e}")
                return "Error processing the file."

            # 创建新的文件名，添加“已处理”
            processed_filename = os.path.splitext(original_filename)[0] + "_已处理.xlsx"

            # 返回处理后的文件
            return send_file(
                file_path,
                as_attachment=True,
                download_name=processed_filename
            )

    # 渲染主页，显示 prompt 选择和上传表单
    prompts = load_prompts()
    
    # 使用嵌入的 HTML 模板
    index_html = """

    
        <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GPT Excel Processor</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f7f9fc;
            margin: 0;
            padding: 20px;
            height: 100vh;
            box-sizing: border-box;
        }

        h1 {
            margin-bottom: 20px;
            font-size: 2.5rem;
            color: #3a8dff;
            text-align: center;
            font-weight: 600;
        }

        .collapsible {
            background-color: #3a8dff;
            color: white;
            cursor: pointer;
            padding: 15px;
            width: 100%;
            text-align: left;
            border: none;
            outline: none;
            font-size: 18px;
            border-radius: 10px;
            transition: background-color 0.3s ease;
        }

        .collapsible.active, .collapsible:hover {
            background-color: #2f79d2;
        }

        .content {
            padding: 0 18px;
            overflow: hidden;
            max-height: 0; /* Start with 0 height for collapsed state */
            transition: max-height 0.3s ease-out;
            background-color: #f1f1f1;
            border-radius: 10px;
            margin-top: 10px;
            margin-bottom: 10px;
            box-sizing: border-box;
        }

        .content-inner {
            padding: 20px;
            background-color: #fff;
            box-shadow: 0 0 15px rgba(0, 0, 0, 0.05);
            border-radius: 10px;
            box-sizing: border-box;
        }

        .prompt-list {
            margin: 20px 0;
        }

        .prompt-item {
            margin-bottom: 15px;
        }

        .prompt-title {
            background-color: #4caf50;
            color: white;
            cursor: pointer;
            padding: 12px;
            width: 100%;
            border: none;
            outline: none;
            text-align: left;
            border-radius: 10px;
            font-size: 16px;
            transition: background-color 0.3s ease;
        }

        .prompt-title.active, .prompt-title:hover {
            background-color: #43a047;
        }

        .prompt-content {
            padding: 15px;
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.5s ease-out;
            background-color: #f9f9f9;
            border-radius: 10px;
            min-height: 80px;
        }

        .scrollable {
            max-height: 300px;
            overflow-y: auto;
            padding: 10px;
            background-color: #ffffff;
            border-radius: 8px;
            box-shadow: 0px 2px 8px rgba(0,0,0,0.05);
        }

        input[type="text"], textarea, select {
            width: 100%;
            padding: 12px;
            margin: 10px 0;
            border: 1px solid #ddd;
            border-radius: 8px;
            font-size: 16px;
            box-shadow: inset 0px 1px 2px rgba(0,0,0,0.05);
        }

        input[type="file"] {
            margin: 20px 0;
            font-size: 16px;
        }

        input[type="submit"] {
            background-color: #3a8dff;
            color: white;
            padding: 12px 20px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 16px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            transition: background-color 0.3s ease, box-shadow 0.3s ease;
        }

        input[type="submit"]:hover {
            background-color: #3375d0;
            box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
        }

        .actions {
            margin-top: 10px;
            display: flex;
            gap: 10px;
        }

        .actions button {
            background-color: #f44336;
            border: none;
            color: white;
            padding: 10px 15px;
            cursor: pointer;
            border-radius: 8px;
            transition: background-color 0.3s ease;
        }

        .actions button.edit {
            background-color: #4caf50;
        }

        .actions button:hover {
            background-color: #d32f2f;
        }

        .actions button.edit:hover {
            background-color: #43a047;
        }

        #editPromptForm {
            margin-top: 20px;
            background-color: #fff;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0px 1px 10px rgba(0,0,0,0.05);
        }

        .form-section {
            background-color: #ffffff;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0px 2px 10px rgba(0,0,0,0.05);
            margin-bottom: 20px;
        }

        .form-section h2 {
            font-size: 1.5rem;
            margin-bottom: 15px;
            color: #3a8dff;
        }

        /* 加载动画 */
        .loading-spinner {
            display: none;
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3a8dff;
            border-radius: 50%;
            width: 20px;
            height: 20px;
            animation: spin 1s linear infinite;
            margin-left: 10px;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        input[type="submit"].disabled {
            background-color: #ddd;
            color: #888;
            cursor: not-allowed;
            box-shadow: none;
        }
    </style>
</head>
<body>

    <h1>GPT Excel Processor</h1>

    <!-- 上传 Excel 文件 -->
    <div class="form-section">
        <form method="post" enctype="multipart/form-data" id="uploadForm">
            <label for="prompt">Choose System Prompt:</label>
            <select name="prompt" id="prompt">
                {% for prompt in prompts %}
                    <option value="{{ prompt.title }}">{{ prompt.title }}</option>
                {% endfor %}
            </select><br><br>

            <input type="file" name="file" required><br><br>
            <input type="submit" value="Upload" id="uploadBtn">
            <div class="loading-spinner" id="loadingSpinner" style="display: none;"></div>
        </form>
    </div>

    <!-- Add System Prompt 折叠部分 -->
    <button class="collapsible" id="addPromptBtn">Add System Prompt</button>
    <div class="content" id="addPromptContent">
        <div class="content-inner">
            <form method="post" action="/add_prompt">
                <label for="title">Prompt Title:</label><br>
                <input type="text" name="title" required><br><br>
                <label for="content">Prompt Content:</label><br>
                <textarea name="content" required></textarea><br><br>
                <input type="submit" value="Add Prompt">
            </form>
        </div>
    </div>

    <!-- Existing Prompts 折叠部分 -->
    <button class="collapsible" id="managePromptsBtn">Existing Prompts</button>
    <div class="content" id="managePromptsContent">
        <div class="content-inner">
            <h2>Existing Prompts</h2>
            <div class="prompt-list">
                {% for prompt in prompts %}
                <div class="prompt-item">
                    <button class="prompt-title" onclick="togglePromptContent(this)">{{ prompt.title }}</button>
                    <div class="prompt-content">
                        <div class="scrollable">
                            <p>{{ prompt.content }}</p>
                        </div>
                        <div class="actions">
                            <form method="post" action="/delete_prompt" style="display:inline;">
                                <input type="hidden" name="title" value="{{ prompt.title }}">
                                <button type="submit">Delete</button>
                            </form>
                            <button class="edit" onclick="editPrompt('{{ prompt.title }}', '{{ prompt.content }}')">Edit</button>
                        </div>
                    </div>
                </div>
                {% endfor %}
            </div>

            <!-- 编辑 Prompt 表单 -->
            <div id="editPromptForm" style="display:none;">
                <h2>Edit System Prompt</h2>
                <form method="post" action="/edit_prompt">
                    <label for="title">Prompt Title:</label><br>
                    <input type="text" name="title" id="editTitle" required><br><br>
                    <label for="content">Prompt Content:</label><br>
                    <textarea name="content" id="editContent" required></textarea><br><br>
                    <input type="submit" value="Update Prompt">
                </form>
            </div>
        </div>
    </div>

    <script>
        const uploadForm = document.getElementById("uploadForm");
        const uploadBtn = document.getElementById("uploadBtn");
        const loadingSpinner = document.getElementById("loadingSpinner");

        // 添加提交事件监听器
        uploadForm.addEventListener("submit", function(event) {
            // 禁用按钮并显示加载动画
            uploadBtn.disabled = true;
            uploadBtn.classList.add("disabled");
            loadingSpinner.style.display = "inline-block";

            // 模拟请求完成后操作（如果你没有用 AJAX 或 fetch）
            // 如果使用 AJAX/fetch，请把这个模拟部分替换为实际的请求回调
            setTimeout(function() {
                // 恢复按钮状态和隐藏加载动画
                loadingSpinner.style.display = "none";
                uploadBtn.disabled = false;
                uploadBtn.classList.remove("disabled");
            }, 3000); // 模拟 3 秒的加载时间
        });

        // Function to toggle collapsible content
        function toggleCollapsible(button, content) {
            button.classList.toggle("active");
            if (content.style.maxHeight) {
                content.style.maxHeight = null;
            } else {
                content.style.maxHeight = content.scrollHeight + "px";
            }
        }

        // Add System Prompt 折叠栏
        const addPromptBtn = document.getElementById("addPromptBtn");
        const addPromptContent = document.getElementById("addPromptContent");

        addPromptBtn.addEventListener("click", function() {
            toggleCollapsible(addPromptBtn, addPromptContent);
        });

        // Existing Prompts 折叠栏
        const managePromptsBtn = document.getElementById("managePromptsBtn");
        const managePromptsContent = document.getElementById("managePromptsContent");

        managePromptsBtn.addEventListener("click", function() {
            toggleCollapsible(managePromptsBtn, managePromptsContent);
        });

        // Toggle individual prompt content
        function togglePromptContent(button) {
            const content = button.nextElementSibling;
            button.classList.toggle("active");
            if (content.style.maxHeight) {
                content.style.maxHeight = null;
            } else {
                content.style.maxHeight = content.scrollHeight + "px";
            }
        }

        // 显示编辑表单并填充数据
        function editPrompt(title, content) {
            document.getElementById("editTitle").value = title;
            document.getElementById("editContent").value = content;
            document.getElementById("editPromptForm").style.display = "block";
        }
    </script>

</body>
</html>


    """
    
    return render_template_string(index_html, prompts=prompts)

# 定义一个函数，用于在服务器启动后自动打开浏览器
def open_browser():
    webbrowser.open("http://127.0.0.1:5000")

if __name__ == '__main__':
    # 如果是在主进程运行，则打开浏览器（避免在调试模式下的子进程中执行）
    if not is_running_from_reloader():
        threading.Timer(1, open_browser).start()

    # 启动 Flask 应用
    app.run(debug=True)
